package com.zjt.swipeview;

import android.app.Activity;
import android.support.annotation.NonNull;
import android.support.v4.widget.NestedScrollView;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;

import com.zjt.swipeview.component.AutoLoadLayout;
import com.zjt.swipeview.component.CompatNestedScrollView;
import com.zjt.swipeview.component.SwipeLayout;
import com.zjt.swipeview.event.OnLoadMoreListener;
import com.zjt.swipeview.event.OnLoadRetryListener;
import com.zjt.swipeview.event.OnLoadStateChangeListener;
import com.zjt.swipeview.event.OnRefreshListener;
import com.zjt.swipeview.util.ViewUtil;

/**
 * <p>Title: </p>
 * <p>Description: </p>
 * <p>Copyright: Copyright (c) 2017</p>
 * <P>Company: </p>
 *
 * @author zhengjianting
 * @time 2017/11/23 0023 下午 4:33
 */

public class SwipeView {

    private SwipeLayout mSwipeToLoadLayout;
    private OnLoadStateChangeListener mOnLoadStateChangeListener;
    private LoadState mLoadState = LoadState.DEFAULT;
    private boolean isFirstRefresh = true;

    private SwipeView(SwipeLayout swipeToLoadLayout) {
        mSwipeToLoadLayout = swipeToLoadLayout;
    }

    private SwipeView(final SwipeLayout swipeToLoadLayout, NestedScrollView scrollView,
                      final AutoLoadLayout autoLoadLayout, final OnLoadRetryListener listener) {
        mSwipeToLoadLayout = swipeToLoadLayout;
        if(autoLoadLayout.getFooterView() instanceof OnLoadStateChangeListener) {
            mOnLoadStateChangeListener = (OnLoadStateChangeListener) autoLoadLayout.getFooterView();
        }
        scrollView.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener() {
            @Override
            public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
                if(ViewUtil.isInScreen((Activity) v.getContext(), autoLoadLayout.getFooterView())) {
                    onFooterVisible();
                    autoLoadLayout.getFooterView().setVisibility(View.VISIBLE);
                }
            }
        });
        autoLoadLayout.getFooterView().setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(mLoadState == LoadState.LOAD_FAIL && listener != null) {
                    listener.onLoadRetry();
                }
            }
        });
    }

    public static Builder with(@NonNull View view) {
        if(view.getParent() == null) {
            throw new IllegalArgumentException("view must have a parent");
        }
        return new Builder(view);
    }

    public static Builder in(@NonNull SwipeLayout swipeLayout) {
        return new Builder(swipeLayout);
    }

    public static Builder in(@NonNull SwipeLayout swipeLayout, View targetView) {
        return new Builder(swipeLayout, targetView);
    }

    public void startFirstRefresh() {
        mSwipeToLoadLayout.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
            @Override
            public boolean onPreDraw() {
                mSwipeToLoadLayout.getViewTreeObserver().removeOnPreDrawListener(this);
                mSwipeToLoadLayout.setRefreshing(true);
                return true;
            }
        });
    }

    public void setRefreshing(boolean isRefreshing) {
        mSwipeToLoadLayout.setRefreshing(isRefreshing);
        mSwipeToLoadLayout.requestLayout();

        if(isFirstRefresh) {
            mSwipeToLoadLayout.getTargetView().requestLayout();
            isFirstRefresh = false;
        }
    }

    public void setLoadingMore(boolean isLoadingMore) {
        mSwipeToLoadLayout.setLoadingMore(isLoadingMore);
        if(isLoadingMore) {
            if(mOnLoadStateChangeListener != null) {
                mOnLoadStateChangeListener.onLoading();
                mLoadState = LoadState.LOADING;
            }
        } else {
            mLoadState = LoadState.DEFAULT;
        }
    }

    public void setRefreshEnabled(boolean refreshEnabled) {
        mSwipeToLoadLayout.setRefreshEnabled(refreshEnabled);
    }

    public void setLoadMoreEnable(boolean loadMoreEnable) {
        mSwipeToLoadLayout.setLoadMoreEnabled(loadMoreEnable);
    }

    public void onLoadFinish() {
        if(mOnLoadStateChangeListener != null) {
            mOnLoadStateChangeListener.onLoadFinish();
        }
        mLoadState = LoadState.LOAD_FINISH;
    }

    public void onLoadFail() {
        if(mOnLoadStateChangeListener != null) {
            mOnLoadStateChangeListener.onLoadFail();
        }
        mLoadState = LoadState.LOAD_FAIL;
    }

    public void onLoadReset() {
        mLoadState = LoadState.DEFAULT;
    }

    private void onFooterVisible() {
        switch (mLoadState) {
            case DEFAULT:
                mSwipeToLoadLayout.getLoadMoreListener().onLoadMore();
                if(mOnLoadStateChangeListener != null) {
                    mOnLoadStateChangeListener.onLoading();
                }
                mLoadState = LoadState.LOADING;
                break;
        }
    }

    public static class Builder {
        private View mTargetView;
        private View mRefreshView;
        private View mLoadMoreView;
        private OnRefreshListener mOnRefreshListener;
        private OnLoadMoreListener mOnLoadMoreListener;
        private OnLoadRetryListener mLoadRetryListener;
        private boolean mRefreshEnable = true;
        private boolean mLoadMoreEnable = true;
        private boolean mIsAutoLoadMore = false;
        private boolean mIsContainTargetView = false;
        private int mStyle = SwipeLayout.STYLE.ABOVE;

        private SwipeLayout mSwipeLayout;

        Builder(View targetView) {
            mTargetView = targetView;
            mSwipeLayout = new SwipeLayout(targetView.getContext());
        }

        Builder(SwipeLayout swipeLayout) {
            mSwipeLayout = swipeLayout;
            mTargetView = mSwipeLayout.findViewById(R.id.esv_swipe_target);
            mIsContainTargetView = true;
        }

        Builder(SwipeLayout swipeLayout, View targetView) {
            mTargetView = targetView;
            mSwipeLayout = swipeLayout;
        }

        public Builder onRefresh(OnRefreshListener listener) {
            mOnRefreshListener = listener;
            return this;
        }

        public Builder onLoadMore(OnLoadMoreListener listener) {
            mOnLoadMoreListener = listener;
            return this;
        }

        public Builder onLoadRetry(OnLoadRetryListener listener) {
            mLoadRetryListener = listener;
            return this;
        }

        public Builder refreshView(View refreshView) {
            mRefreshView = refreshView;
            return this;
        }

        public Builder refreshView(int viewId) {
            mRefreshView = LayoutInflater.from(mTargetView.getContext())
                    .inflate(viewId, (ViewGroup) mTargetView.getParent(), false);
            return this;
        }

        public Builder loadMoreView(View loadMoreView) {
            mLoadMoreView = loadMoreView;
            return this;
        }

        public Builder loadMoreView(int viewId) {
            mLoadMoreView = LayoutInflater.from(mTargetView.getContext())
                    .inflate(viewId, (ViewGroup) mTargetView.getParent(), false);
            return this;
        }

        public Builder refreshEnable(boolean enable) {
            mRefreshEnable = enable;
            return this;
        }

        public Builder loadMoreEnable(boolean enable) {
            mLoadMoreEnable = enable;
            return this;
        }

        public Builder autoLoadMore(boolean isAuto) {
            mIsAutoLoadMore = isAuto;
            return this;
        }

        public Builder style(int style) {
            mStyle = style;
            return this;
        }

        public SwipeView build() {
            if(mRefreshView == null) {
                mRefreshView = LayoutInflater.from(mTargetView.getContext())
                        .inflate(R.layout.esv_google_hook_header, (ViewGroup) mTargetView.getParent(), false);
            }

            if(mLoadMoreView == null) {
                mLoadMoreView = LayoutInflater.from(mTargetView.getContext())
                        .inflate(R.layout.esv_google_hook_footer, (ViewGroup) mTargetView.getParent(), false);
            }

            if(mIsAutoLoadMore) {
                CompatNestedScrollView scrollView = new CompatNestedScrollView(mTargetView.getContext());
                AutoLoadLayout autoLoadLayout = new AutoLoadLayout(mTargetView.getContext());

                attachContainer(mTargetView, false, mSwipeLayout, scrollView, autoLoadLayout);
                autoLoadLayout.addView(mTargetView, mLoadMoreView);
                autoLoadLayout.getFooterView().setVisibility(View.INVISIBLE);

                if(mTargetView instanceof RecyclerView) {
                    ((RecyclerView)mTargetView).setNestedScrollingEnabled(false);
                }

                mSwipeLayout.setTargetView(scrollView);
                mSwipeLayout.setLoadMoreEnabled(false);
                initCommon(mSwipeLayout);
                return new SwipeView(mSwipeLayout, scrollView, autoLoadLayout, mLoadRetryListener);
            } else {
                if(!mIsContainTargetView) {
                    attachContainer(mTargetView, true, mSwipeLayout);
                }
                mSwipeLayout.setTargetView(mTargetView);
                mSwipeLayout.setLoadMoreFooterView(mLoadMoreView);
                mSwipeLayout.setLoadMoreEnabled(mLoadMoreEnable);
                initCommon(mSwipeLayout);
                return new SwipeView(mSwipeLayout);
            }
        }

        private void initCommon(SwipeLayout swipeToLoadLayout) {
            swipeToLoadLayout.setRefreshHeaderView(mRefreshView);
            swipeToLoadLayout.setRefreshListener(mOnRefreshListener);
            swipeToLoadLayout.setLoadMoreListener(mOnLoadMoreListener);
            swipeToLoadLayout.setHeaderSwipeStyle(mStyle);
            swipeToLoadLayout.setFooterSwipeStyle(mStyle);
            swipeToLoadLayout.setRefreshEnabled(mRefreshEnable);
        }
    }

    private static void attachContainer(View targetView, boolean addTargetView, ViewGroup... containers) {
        if(targetView.getParent() == null) {
            throw new IllegalArgumentException("target view must be have a parent");
        }
        if(containers.length == 0) {
            throw new IllegalArgumentException("at least have one container");
        }

        ViewGroup parent = (ViewGroup) targetView.getParent();
        int index = parent.indexOfChild(targetView);

        if(!parent.equals(containers[0])) {
            swapLayoutParams(containers[0], targetView);

            parent.removeView(targetView);
            parent.addView(containers[0], index);
        } else {
            parent.removeView(targetView);
        }

        for(int i=1; i<containers.length; i++) {
            containers[i].setLayoutParams(targetView.getLayoutParams());
            containers[i-1].addView(containers[i]);
        }

        if(addTargetView) {
            containers[containers.length-1].addView(targetView);
        }
    }

    private static void swapLayoutParams(ViewGroup container, View targetView) {
        ViewGroup.LayoutParams containerLayoutParams = container.getLayoutParams();
        ViewGroup.LayoutParams targetLayoutParams = targetView.getLayoutParams();

        if(containerLayoutParams == null) {
            containerLayoutParams = new ViewGroup.MarginLayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT
            );
        }

        containerLayoutParams.width = targetLayoutParams.width;
        containerLayoutParams.height = targetLayoutParams.height;

        container.setLayoutParams(targetLayoutParams);
        targetView.setLayoutParams(containerLayoutParams);
    }
}
